package message;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQTopic;

import javax.jms.*;
import java.io.DataInputStream;
import java.io.Serializable;
import java.util.Objects;

/**
 * Created with Intel IDEA.
 * 消息类型：TextMessage, StreamMessage, MapMessage, ObjectMessage, BytesMessage, Message
 * @Auther: gjt
 * @Date: 2024/11/3 11:10
 */
public class MessageType {

    private static String USERNAME = ActiveMQConnection.DEFAULT_USER;
    private static String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
    private static String BROKER = ActiveMQConnection.DEFAULT_BROKER_URL;

    private static String TOPIC_NAME = "topic";


    public void get(){
        // 创建主题连接工厂
        TopicConnectionFactory conFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER);


        try {
            TopicConnection topicConnection = conFactory.createTopicConnection();
            if(Objects.isNull(topicConnection)){
                System.out.println("topicConnection is null");
            }


            TopicSession topicSession = topicConnection.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
            Topic topic = new ActiveMQTopic(TOPIC_NAME);
            TopicPublisher publisher = topicSession.createPublisher(topic);


            /**
             * 类型 message: 不含有有效负载的消息，仅仅包含jms消息头和消息属性，仅限于事件通知。
             *  列子： 为了广播通知异常，可以发布一条不含有任何有效负载的异常文本消息
             */
            Message message = topicSession.createMessage();


            /**
             * 类型：textMessage
             * 使用String类型数据 作为有效负载
             */
            TextMessage textMessage = topicSession.createTextMessage();// 这个中消息没有有效负载，可以在setText()设置有效负载
            textMessage.setText("name");

            TextMessage textMessage1 = topicSession.createTextMessage("name");// 这个消息使用String 作为参数，生产出准备就绪可以发送给的消息
            publisher.publish(textMessage1);


            /**
             * 类型：ObjectMessage
             * 使用 可序列化java对象数据 作为有效负载
             */
            ObjectMessage objectMessage = topicSession.createObjectMessage();// 这个中消息没有有效负载，可以在setText()设置有效负载
            objectMessage.setObject("name");// 因为String 实现了序列化接口，所以可以设置对象

            // 当一个消息中没有负载，将返回null
            publisher.publish(objectMessage);
            String object = (String)objectMessage.getObject();


            /**
             * 类型：BytesMessage
             * 使用 一组原始类型字节流 数据 作为有效负载，对jms客户端时透明的。
             */
            BytesMessage bytesMessage = topicSession.createBytesMessage();
            bytesMessage.writeChar('R');
            bytesMessage.writeInt(1);
            bytesMessage.writeUTF("OReilly");

            // bytesMessage 有效负载是一个原始字节流，可以使用任何形式的类去读取，但是可能会出错，尽量使用相同的类型和顺序读取和写入
            // java 中的 byte和 short 都是有符号的  范围（-32768 - 32767； -128 - 127）
            // 无符号的 byte 范围（0 - 255） short 范围（0 - 65535）
            int i = bytesMessage.readUnsignedByte();

            /**
             * 在读取BytesMessage 中出现异常，可以从中回复，而不需要回复消息，将字节流的指针重新设定reset，指针返回起始位置，并将消息设置为只读模式，
             * 如果需要的话可以显示的调用此方法，但是在传送中他始终隐式的调用
             */


            /**
             * 类型：StreamMessage
             * 使用 java原始数据类型  作为有效负载。将字节流映射为java 原始数据类型
             * StreamMessage 和 BytesMessage 时不同的，StreamMessage 保持了写入流时的顺序和原始数据类型
             * 比如 写入时long  读取使用short StreamMessage 将会抛出异常,而BytesMessage 则不会
             */
            /**
             * 类型转换规则
             *  write          read
             *  boolean         boolean,String
             *  byte            byte,short,int,long,String
             *  char            char,String
             *  double          double,String
             *  float           float,double,String
             *  int             int,long,String
             *  long            long,String
             *  short           short,int,long,String
             *  String          String,int,long,float,double,short,byte,boolean
             *  byte[]          byte[]
             */
            // 在消息重新传送前
            if(message.getJMSRedelivered()){

            }


            /**
             * 类型：MapMessage
             * 使用 一组名值对  作为有效负载。将字节流映射为java 原始数据类型
             */
            MapMessage mapMessage = topicSession.createMapMessage();
            mapMessage.setString("name", "gjt");
            if(mapMessage.itemExists("name")){
                System.out.println("消息名字是" + mapMessage.getString("name")+ "存在");
            }

            /**
             * 在消息发送后，唯一可以使用的方法，clearBody,清空消息的有效负载。
             */


            /**
             * 客户端确认的消息：
             *  模式有： AUTOACKNOWLEDGE，CLIENT_ACKNOWLEDGE，DUPS_OK_ACKNOWLEDGE
             */
            // CLIENT_ACKNOWLEDGE 这种模式时消费者在收到一条消息都会显示式确认消息
            topicConnection.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE);
            // 此方法的作用就在此 其他模式不需要这个方法
            message.acknowledge();

            /**
             * notes: 一个会话是事务性会话，则这个会话将会忽略所有的客户确认模式， 如果事务被回滚，则消息也不会被确认。
             */
        } catch (JMSException e) {
//            可以在这个里发布异常事件
            throw new RuntimeException(e);


        }
    }

}
